// 这个文件就是二次封装axios， 因为你要给axios加一些 请求基地址，或者配置拦截器，
import store from '@/store'
import axios from 'axios'
import { Message } from 'element-ui'
import router from '@/router'

// 怎么封装？去看官网，或者百度搜索  “vue axios 二次封装”
const service = axios.create({
  // baseURL 是所有请求的前缀， 基地址
  // baseURL: '/api'  不要写死，写成变量，让不同的环境，自动变换
  baseURL: process.env.VUE_APP_BASE_API,
  // timeout请求超时时间，超过了6s就会报错
  timeout: 6000
})

// 请求拦截器 --- 请求之前执行的函数， 2个参数， 请求发成功的回调函数，请求发失败的回调函数
// 请求拦截器有几个参数？
// 有两个参数， 分别是两个回调函数(开始的时候不执行，回过头来，在特定的时机在执行)
// 第一个回调函数，是请求发送成功以后执行的函数
// 第二个回调函数，是请求发送失败以后执行的函数
service.interceptors.request.use((config) => {
  // console.log('1请求发成功的回调函数', config)
  // 后面会在这里，给所有请求，加一个请求头
  // Conten-Type 这个是 被axios 默认设置为了 appliaction/json
  // Authorization 这个值 axios默认没有， 需要我们手动配置
  if (store.state.user.token) {
    config.headers.Authorization = `Bearer ${store.state.user.token}`
  }

  return config
}, (error) => {
  // console.log('2请求发送失败的回调函数')
  return Promise.reject(error)
})

// 响应拦截器 --- 服务器给相应数据到业务之前
// 响应拦截器的参数？
// 有2个参数，分别是2个回调函数
// 第一个回调函数。 是服务器响应成功以后执行的回调函数
// 第二个回调函数，是服务器响应式失败以后（401 500 403 404 。。。） 以后执行的回调函数
service.interceptors.response.use((response) => {
  // 在这里做一个前置判断
  if (response.data instanceof Blob) return response.data
  // http状态码是 200  才会走第一个响应拦截器的回调函数
  // console.log('3服务器响应成功, ', response.data)
  // 响应成功以后，对数据进行脱壳处理
  if (response.data.success) {
    // 这个if分支，表示业务成功
    return response.data
  } else {
    // 这个if分支，表示业务失败，应该给用户提示，并且用Promise.reject返回，主要是让我们的业务代码，执行catch里面去
    // 给用户一些使用提示，提示的话，不能使用alert，卡死浏览器，不好，要用element-ui的一些 提示组件
    // console.log('业务报错了')
    // 下面这种代码，是在.vue后缀的文件里面用的，硬因为this必须要是 vue组件实例
    // 而我们这个 .js文件是 不能使用this的，或者说下面this指向的是undefined
    // this.$message('这是一条消息提示')
    Message.error({ message: response.data.message })
    return Promise.reject(response)
  }
}, (error) => {
  // http状态码是 4xx  5xx 就会走这个函数
  // console.log('4服务器响应失败')
  // 涉及到Promise的底层， promise3个状态， pending 等待 resolve 成功 reject 失败
  // 这里如果 reject，那么在业务代码那边，就会执行 .catch的代码
  // 这里如果 resolve，那么在业务代码那边，就会执行 .then的代码
  // 因为这里已经是报错了，所以，我们这里必须写reject，告诉业务代码，我们这里报错了，请你用catch接受一下
  // 但是自己心里要清楚，如果这里写resolve，那么业务那边走的绝对是then里面的代码

  // 这里要处理error对象，不要用console.log，应该用console.dir
  // console.dir(error)
  // 以后写比较长的对象的.的语法，都用?. 去代替 直接.， 防止一些 xxx of undefined
  if (error?.response?.status === 401) {
    // 只要进入了这个if分支，那么证明token失效，就需要跳转回去登录页面，并且情况所有的token和userInfo的信息
    // store.dispatch('/user/logoutAction')  // 这里是模块，不能加/。 路由跳转才能加/
    store.dispatch('user/logoutAction')
    router.push('/login')
  }
  return Promise.reject(error)
})

// 下面导出是 默认导出 ---- 怎么样导出（需不需要大括号）
export default service

// const a = {
//   b: {
//     c: {
//       d: {
//         e: 1
//       }
//     }
//   }
// }
// console.log(a?.b?.c?.d?.e?.f?.g?.d)
